#include <iostream>
#include <functional>
#include <vector>
#include <stack>
#include <unordered_map>
#include <thread>

using namespace std;

/*
int func(int a, int b){
    return a + b;
}

struct Func{
public:
    int operator()(int a, int b){
        return a + b;
    }
};

class Plus{
public:
    static int plus(int a, int b){
        return a + b;
    }
    int nsPlus(int a, int b){
        return a + b;
    }
};

void test(){
    function<int(int, int)> func1 = func;
    cout << func1(1, 2) << endl;

    function<int(int, int)> func2 = Func();
    cout << func2(1, 2) << endl;

    //类的静态成员函数
    //&可省略
    //function<int(int, int)> func3 = &Plus::plus;
    function<int(int, int)> func3 = Plus::plus;
    cout << func3(1, 2) << endl;

    //类的非静态成员函数
    //&不可省略
    function<int(Plus, int, int)> func4 = &Plus::nsPlus;
    cout << func4(func(), 1, 2) << endl;

    function<int(int, int)> func5 = [](int a, int b){return a + b;};
    cout << func5(1, 2) << endl;
}

template<class F, class N>
N useF(F f, N num1, N num2){
    static int count = 0;
    cout << "count:" << ++count << endl;
    cout << &count << endl;
    return f(num1, num2);
}

void test1(){
    cout << useF(func, 1, 2) << endl;
    cout << useF(Func(), 1, 2) << endl;
    cout << useF([](int a, int b){return a + b;}, 1, 2) << endl;
}

void test2(){
    function<int(int, int)> func1 = func;
    function<int(int, int)> func2 = Func();
    function<int(int, int)> func5 = [](int a, int b){return a + b;};
    cout << useF(func1, 1, 2) << endl;
    cout << useF(func2, 1, 2) << endl;
    cout << useF(func5, 1, 2) << endl;
}

int main() {
    test2();
    return 0;
}
*/

//https://leetcode.cn/problems/evaluate-reverse-polish-notation/
/*
class Solution {
public:
    static int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for (const auto& str : tokens) {
            int left, right;
            if (str == "+" || str == "-" || str == "*" || str == "/"){
                right = st.top();
                st.pop();
                left = st.top();
                st.pop();
                switch (str[0]) {
                    case '+':
                        st.push(left + right);
                        break;
                    case '-':
                        st.push(left - right);
                        break;
                    case '*':
                        st.push(left * right);
                        break;
                    case '/':
                        st.push(left / right);
                        break;
                    default:
                        break;
                }
            } else
                st.push(stoi(str));
        }
        return st.top();
    }
};

class Solution {
public:
    static int evalRPN(vector<string>& tokens) {
        stack<int> st;
        unordered_map<string, function<int(int, int)>> opMap = {
                {"+", [](int a, int b){return a + b;}},
                {"-", [](int a, int b){return a - b;}},
                {"*", [](int a, int b){return a * b;}},
                {"/", [](int a, int b){return a / b;}}
        };
        for (const auto& str : tokens) {
            int left, right;
            if (str == "+" || str == "-" || str == "*" || str == "/"){
                right = st.top();
                st.pop();
                left = st.top();
                st.pop();
                st.push(opMap[str](left, right));
            } else
                st.push(stoi(str));
        }
        return st.top();
    }
};*/

/*
int func(int a, int b){
    return a + b;
}

void test1(){
    function<int(int, int)> func1 = func;
    function<int(int, int)> func2 = bind(func, placeholders::_1, placeholders::_2);
    function<int(int)> func3 = bind(func, placeholders::_1, 10);
    function<int(int, int)> func4 = bind(func, placeholders::_2, placeholders::_1);
    cout << func1(1, 2) << endl;
    cout << func2(1, 2) << endl;
    cout << func3(1) << endl;
    cout << func4(1, 2) << endl;
}

class Sub{
public:
    Sub(int rate)
    :_rate(rate){}

    int func(int a, int b){
        return (a - b) * _rate;
    }
private:
    int _rate;
};

//调整参数个数
void test2(){
    function<int(Sub, int, int)> fSub = &Sub::func;
    cout << fSub(Sub(2), 10, 20) << endl;
    function<int(int, int)> fSub1 = bind(&Sub::func, Sub(2), placeholders::_1, placeholders::_2);
    cout << fSub1(10, 20) << endl;
    function<int(Sub, int)> fSub2 = bind(&Sub::func, placeholders::_1, 100, placeholders::_2);
    cout << fSub2(Sub(3), 20) << endl;
}

int main(){
    test2();
    return 0;
}
*/

//C++异常
/*
void func1(){
    throw string("an exception");
    //throw 1;
}

void func2(){
    func1();
}

void test(){
    try{
        func2();
    }
    catch (const string& s){
        cout << "wrong:" << s << endl;
    }
    catch (...){
        cout << "unknown" << endl;
    }
}

void func3(){
    int* array = new int[10];
    func1();

    delete[] array;
}

void func4(){
    int* array = new int[10];
    try {
        func1();
    }
    catch (...){
        delete[] array;
        throw;
    }
    delete[] array;
}

void test1(){
    try{
        func4();
    }
    catch (const string& s){
        cout << "wrong:" << s << endl;
    }
    catch (...){
        cout << "unknown" << endl;
    }
}

int main(){
    test1();
    return 0;
}
*/

class Exception{
public:
    Exception(int errId, const string& errMsg):_errId(errId), _errMsg(errMsg){}

    int GetErrId() const{
        return _errId;
    }

    virtual string what() const{
        return _errMsg;
    }

protected:
    int _errId;
    string _errMsg;
};

class SqlException : public Exception{
public:
    SqlException(int errId, const string& errMsg, const string& sql): Exception(errId, errMsg), _sql(sql){}

    virtual string what() const{
        string msg = "sqlException: ";
        msg += _errMsg;
        msg += "-->";
        msg += _sql;
        return msg;
    }

private:
    string _sql;
};

class CacheException : public Exception{
public:
    CacheException(int errId, const string& errMsg): Exception(errId, errMsg){}

    virtual string what() const{
        string msg = "CacheException: ";
        msg += _errMsg;
        return msg;
    }
};

class HttpServerException : public Exception{
public:
    HttpServerException(int errId, const string& errMsg, const string& type): Exception(errId, errMsg), _type(type){}

    virtual string what() const{
        string msg = "HttpServerException: ";
        msg += _errMsg;
        msg += "-->";
        msg += _type;
        return msg;
    }
private:
    const string _type;
};

void SQLMgr()
{
    srand(time(nullptr));
    if (rand() % 2 == 0)
    {
        throw SqlException(100, "权限不足", "select * from name = '张三'");
    }

    cout << "调用成功" << endl;
}

void CacheMgr()
{
    srand(time(0));
    if (rand() % 5 == 0)
    {
        throw CacheException(100,"权限不足");
    }
    else if (rand() % 6 == 0)
    {
        throw CacheException(101, "数据不存在");
    }

    SQLMgr();
}

void HttpServer()
{
    // 模拟服务出错
    srand(time(0));
    if (rand() % 3 == 0)
    {
        throw HttpServerException(100, "请求资源不存在", "get");
    }
    else if (rand() % 7 == 0)
    {
        throw HttpServerException(101, "权限不足", "post");
    }

    CacheMgr();
}

void test(){
    while (true){
		this_thread::sleep_for(chrono::seconds(1));
		try{
			HttpServer();
		}
        // 这里捕获父类对象就可以
		catch (const Exception& e) {
			// 多态
			cout << e.what() << endl;
		}
		catch (...){
			cout << "Unknown Exception" << endl;
		}
	}
}

int main(){
    test();
    return 0;
}